package com.dbflow5.query;

import com.dbflow5.database.DatabaseWrapper;
import com.dbflow5.database.FlowCursor;
import com.dbflow5.query.property.IProperty;

import java.util.List;

/**
 * Description: Combines basic transformations and query ops into a base class.
 */
public abstract class BaseTransformable<TModel> extends BaseModelQueriable<TModel> implements Transformable<TModel>, WhereBase<TModel> {
    private final Class<TModel> tableClass;

    protected BaseTransformable(Class<TModel> table){
        super(table);
        this.tableClass = table;
    }

    @Override
    public Class<TModel> table() {
        return tableClass;
    }

    public <T> Where<TModel> whereExists(Where<T> where) {
        return where().exists(where);
    }

    public Where<TModel> where(SQLOperator... conditions) {
        return new Where<>(this, conditions);
    }

    public Where<TModel> where(SQLOperator condition) {
        return new Where<>(this, condition);
    }

    @Override
    public FlowCursor cursor(DatabaseWrapper databaseWrapper) {
        return where().cursor(databaseWrapper);
    }

    @Override
    public Where<TModel> groupBy(NameAlias... nameAliases) {
        return where().groupBy(nameAliases);
    }

    @Override
    public Where<TModel> groupBy(IProperty<?>... properties) {
        return where().groupBy(properties);
    }

    @Override
    public Where<TModel> orderBy(NameAlias nameAlias, boolean ascending) {
        return where().orderBy(nameAlias, ascending);
    }

    @Override
    public Where<TModel> orderBy(IProperty<?> property, boolean ascending) {
        return where().orderBy(property, ascending);
    }

    @Override
    public Where<TModel> orderByAll(List<OrderBy> orderByList) {
        return where().orderByAll(orderByList);
    }

    @Override
    public Where<TModel> orderBy(OrderBy orderBy) {
        return where().orderBy(orderBy);
    }

    @Override
    public Where<TModel> limit(long count) {
        return where().limit(count);
    }

    @Override
    public Where<TModel> offset(long offset) {
        return where().offset(offset);
    }

    @Override
    public Where<TModel> having(SQLOperator... conditions) {
        return where().having(conditions);
    }

    @Override
    public abstract BaseTransformable<TModel> cloneSelf();

    @Override
    public List<TModel> queryList(DatabaseWrapper databaseWrapper) {
        checkSelect("query");
        return super.queryList(databaseWrapper);
    }

    @Override
    public TModel querySingle(DatabaseWrapper databaseWrapper) {
        checkSelect("query");
        limit(1);
        return super.querySingle(databaseWrapper);
    }

    private void checkSelect(String methodName) {
        if (!(queryBuilderBase() instanceof Select)) {
            throw new IllegalArgumentException("Please use "+methodName+"(). The beginning is not a Select");
        }
    }
}
